//
//  QGStatusViewModel.swift
//  斯威夫特微博
//
//  Created by youyoumacmini3 on 2017/7/19.
//  Copyright © 2017年 youyoumacmini3. All rights reserved.
//

import Foundation


/// 单条微博的视图模型
/*
 如果没有任何父类，如果在开发室调试，输出调试信息，需要
 1. 遵守 CustomStringConvertible
 2. 实现 description 计算型属性
 
 关于表格的性能优化
 
 - 尽量少计算，所有需要的素材提前计算好
 - 控件上不要设置圆角半径，所有图像渲染的属性，都要注意
 - 不要动态创建控件，所有需要的控件都要提前创建好，根据数据 隐藏/显示
 - cell中控件的层次越少越好，数量越少越好
 - 要测量，不要猜测
 */

class QGStatusViewModel: CustomStringConvertible {
    // 微博模型
    var status: QGStatus
    
    // 会员图标 = 存储型属性（用内存换CPU）
    var memberIcon: UIImage?
    // 认证类型： -1：没有认证 0：认证用户 2,3,5:企业认证 220：达人
    var vipIcon: UIImage?

    
    // 转发文字
    var retweetedStr: String?
    
    // 评论文字
    var commentStr: String?
    // 点赞文字
    var likeStr: String?
    
    // 来源字符串 （方法一）
    //var sourceStr: String?
    
    
    
    // 配图视图大小
    var pictureViewSize = CGSize()
    
    
    // 如果是被转发微博，原创微博一定没有图
    var picURLs: [QGPicture]? {
        // 如果有被转发的微博，返回被转发微博配图
        // 如果没有被转发微博，返回原创微博配图
        // 都没有 返回 nil
        return status.retweeted_status?.pic_urls ?? status.pic_urls
    }
    
    /// 微博正文的属性文本
    var statusAttrText: NSAttributedString?
    // 被转发微博的文字
    var retweetedAttrText: NSAttributedString?
    
    // 行高
    var rowHeight: CGFloat = 0
    
   
 
    
    /// 构造函数
    ///
    /// - Parameter model: 微博模型
    ///
    /// - return: 微博的视图模型
    init(model: QGStatus) {
        
        
        
        self.status = model
        
     
        //  直接计算出会员图标 /会员等级 0-6
        if (model.user?.mbrank)! > 0 && (model.user?.mbrank)! < 7 {
            let imageName = "common_icon_membership_level\(model.user?.mbrank ?? 1)"
            memberIcon = UIImage(named: imageName)
        }
        
        // 认证图标
        switch model.user?.verified_type ?? -1 {
        case 0:
            vipIcon = UIImage(named: "avatar_vip")
        case 2,3,5:
            vipIcon = UIImage(named: "avatar_enterprise_vip")
        case 220:
            vipIcon = UIImage(named: "avatar_grassroot")
        default:
            break
        }
        
        // 设置底部计数字符串
        retweetedStr = countStr(count: model.reposts_count, defaultStr: "转发")
        commentStr = countStr(count: model.comments_count, defaultStr: "评论")
        likeStr = countStr(count: model.attitudes_count, defaultStr: "赞")
        
        
        // 计算配图视图大小（有原创计算原创，有转发计算的则是转发的）
        pictureViewSize = calcPictureViewSize(count: picURLs?.count)
        
        
        let originalFont = UIFont.systemFont(ofSize: 15)
        let retweetedFont = UIFont.systemFont(ofSize: 14)
        
        
        // 微博正文的属性文本
        statusAttrText = CZEmotionManager.shared.emotionString(string: model.text ?? "", font: originalFont)
        
        // 设置被转发微博的文字
        let retweetedText = "@" + (status.retweeted_status?.user?.screen_name ?? "") + ":" + (status.retweeted_status?.text ?? "")
        retweetedAttrText = CZEmotionManager.shared.emotionString(string: retweetedText, font: retweetedFont)
        
        // 设置来源字符串（方法一）
        //sourceStr = "来自" + (model.source?.cz_href()?.text ?? "")
        
        
        // 计算行高
        updateRowHeight()
        
    }
    
    var description: String {
        return status.description
    }
    
    // 根据当前视图模型内容计算行高
    func updateRowHeight() {
        // 原创微博： 顶部分割视图(12) + 间距(12) + 图像高度(34) + 间距(12) + 正文高度(需要计算) + 配图视图高度(计算) + 间距(12) + 底部视图高度(35)
        // 被转发微博： 顶部分割视图(12) + 间距(12) + 图像高度(34) + 间距(12) + 正文高度(需要计算) + 间距(12) + 间距(12) + 转发文本高度(需要计算) + 配图视图高度(计算) + 间距(12) + 底部视图高度(35)
        
        let margin: CGFloat = 12
        let iconHeight: CGFloat = 34
        let toolBarHeight: CGFloat = 35
        
        var height: CGFloat = 0
        
        let viewSize = CGSize(width: UIScreen.cz_screenWidth() - 2 * margin, height: CGFloat(MAXFLOAT))
        
//        let originalFont = UIFont.systemFont(ofSize: 15)
//        let retweetedFont = UIFont.systemFont(ofSize: 14)
        
        // 1. 计算顶部位置
        height = margin * 2 + iconHeight + margin
        
        // 2. 正文属性高度
        if let text = statusAttrText {
            // 此处没有下面方法的 attributes，因为属性文本中本身已经包含了字体属性
            height += text.boundingRect(with: viewSize, options: [.usesLineFragmentOrigin], context: nil).height
            
//            /* 参数
//              1）预期尺寸，宽度固定，高度尽量大
//              2）选项，换行文本统一使用 usesLineFragmentOrigin
//              3）attributes：指定字体字典
//            */
//            height += (text as NSString).boundingRect(with: viewSize, options: [.usesLineFragmentOrigin], attributes: [NSFontAttributeName: originalFont], context: nil).height
        }
        
        // 3. 判断是否转发微博 - 多出来的(间距(12) + 间距(12) + 转发文本高度)
        if status.retweeted_status != nil {
            height += margin * 2
            
            // 转发文本的高度 - 一定用 retweetedText 已经拼接了@用户名：微博文字
            if let text = retweetedAttrText {
                
                height += text.boundingRect(with: viewSize, options: [.usesLineFragmentOrigin], context: nil).height
                
                
//                height += (text as NSString).boundingRect(with: viewSize, options: [.usesLineFragmentOrigin], attributes: [NSFontAttributeName: retweetedFont], context: nil).height
            }
        }
        
        // 4. 配图视图
        height += pictureViewSize.height
        height += margin
        
        // 5. 底部工具栏
        height += toolBarHeight
        
        // 6. 使用属性记录
        rowHeight = height
        
    }
    
    
    /// 使用单个图像更新配图视图的大小
    ///
    /// 新浪针对单张图片，都是缩略图，但偶尔会有一张特别大的图
    /// 新浪为了鼓励原创，支持 ‘长微博’ ，但有的时候有特别长的微博，长到宽度只有一个点
    ///
    /// - Parameter image: 网络缓存的单张图像
    func updateSingleImageSize(image: UIImage) {
        
        var size = image.size

        let maxWidth: CGFloat = 200
        let miniWidth: CGFloat = 40

        // 过宽图像处理
        if size.width > maxWidth {
            // 设置最大宽度
            size.width = maxWidth
            
            // 等比例调整高度
            size.height = size.width * image.size.height / image.size.width
        }
        
        // 过窄图像处理
        if size.width < miniWidth {
            size.width = miniWidth
            
            // 要特殊处理高度，否则高度太大，会影响用户体验
            size.height = size.width * image.size.height / image.size.width / 4
        }
        
        // 过高图片处理, 图片填充模式就是 scaleToFill,高度减小，会自动裁切
        if size.height > 200 {
            size.height = 200
        }
        
        
        // 特例：有些图像本身就很窄很长 -> 定义一个miniHeight，思路同上
        // 在工作中，如果看到代码有些疑惑的分支处理
        
        
        
        // 注意：由于一开始的设计，尺寸需要增加顶部的12个点，便于布局
        size.height += QGStatusPicViewOutterMargin
        
        // 此处重新设置了配图视图大小
        pictureViewSize = size
        
        // 所以此处也需要更新行高
        updateRowHeight()
    }
    
    
    /// 计算指定数量的图片对应的配图视图的大小
    ///
    /// - Parameter count: 配图数量
    /// - Returns: 配图视图大小
    private func calcPictureViewSize(count: Int?) -> CGSize {
        
        if count == 0 || count == nil {
            return CGSize()
        }
        
        // 2. 计算高度
        // 1> 根据count 知道行数 1~9
        /* 
           1 2 3 = 0 1 2 / 3 = 0 + 1 = 1
           4 5 6 = 3 4 5 / 3 = 1 + 1 = 2
           7 8 9 = 6 7 8 / 3 = 2 + 1 = 3
         */
        let row = CGFloat((count! - 1) / 3) + 1
        
        // 2> 根据行数算高度
        let height = QGStatusPicViewOutterMargin + row * QGStatusPicViewItemWidth + (row - 1) * QGStatusPicViewInnerMargin
        
        return CGSize(width: QGStatusPicViewWidth, height: height)
    }
    
    /// 给定一个数字返回对应的描述结果
    ///
    ///   - count: 数字
    ///   - defaultStr: 默认字符串  转发/评论/赞
    /// - Returns: 描述结果
    private func countStr(count: Int, defaultStr: String) -> String {
        
        if count == 0 {
            return defaultStr
        }
        if count < 10000 {
            return count.description
        }
        return String(format: "%.02f 万", Double(count) / 10000)
    }
}
